import { Helper } from 'babylon-lib/tool/helper';
import { DefaultStage } from '../default-stage';
import { Model } from './model';
import { RawAssetsName } from '../../raw-assets-info';
import { InstancedMesh } from '@babylonjs/core/Meshes/instancedMesh';
import { Mesh } from '@babylonjs/core/Meshes/mesh';
import { Color3 } from '@babylonjs/core/Maths/math.color';
import { Scene } from '@babylonjs/core/scene';
import { GradientSkybox } from 'babylon-lib/preset/gradient-skybox';
import { Vector3 } from '@babylonjs/core/Maths/math.vector';
import { Random } from 'babylon-lib/tool/random';
import { SoldierManager } from './soldier-manager';
import { Bomb } from './bomb';
import { AbstractMesh, AnimationFrame } from 'babylon-lib/index';
import * as Data from '../../data/data';
import { PBRMaterial } from '@babylonjs/core';
import { Wreckage } from './wreckage';


class Landscape {

    private static _fadeReq = {};

    public static readonly maxTime = 600;
    public static readonly delta = 1 / 60;
    public static readonly gravity = 4;
    public static readonly windRand = 0.75;
    public static readonly wind = new Vector3(Random.float(-this.windRand, this.windRand), 0, Random.float(-this.windRand, this.windRand));
    public static readonly zoneCenter = new Vector3(0, 0, 0);
    public static readonly zoneExtend = 300;
    public static readonly coreCenter = new Vector3(Random.float(-100, 100), 0, Random.float(200, 250));
    public static readonly coreExtend = 100;
    public static readonly dangrousPoints: Array<[Vector3, number]> = [];
    public static readonly enemyTargetDirection = new Vector3(0, 0, -1);

    public static initialize(stage: DefaultStage): void {
        this.setModel(stage);
        this.setSky(stage);
        Wreckage.initialize(stage);
        Data.windStrength.value = this.wind.length();
    }

    public static addDangrousPoint(point: Vector3): void {
        this.dangrousPoints.push([new Vector3().copyFrom(point), performance.now()]);
        AnimationFrame.request(() => {
            const cur = performance.now();
            for (let i = 0; i < this.dangrousPoints.length; i++) {
                const dp = this.dangrousPoints[i];
                if (cur - dp[1] > 2000) {
                    this.dangrousPoints.splice(i, 1);
                    i--;
                }
            }
            if (this.dangrousPoints.length === 0) return true;
        }, 100, 200, this._fadeReq);
    }

    public static checkDamage(bomb: Bomb): void {
        for (const sd of SoldierManager.signedSoldiers) {
            const dis = Vector3.DistanceSquared(bomb.entity.absolutePosition, sd.entity.absolutePosition);
            sd.damage(bomb.calculateDamage(dis));
        }
    }

    private static setSky(stage: DefaultStage): void {
        const scn = stage.mainScene;
        scn.fogEnabled = true;
        scn.fogStart = 200;
        scn.fogEnd = 600;
        scn.fogColor = Color3.FromHexString('#888888');
        scn.fogMode = Scene.FOGMODE_LINEAR;

        const skybox = new GradientSkybox('sky', stage.mainScene, {
            values: [0.2, 0.5, 0.8],
            colors: ['#ffffff', '#00375c', '#52baff'],
            size: 1000,
        });

        skybox.mesh.scaling.set(5, 2, 5);
    }

    private static setModel(stage: DefaultStage): void {
        const all = Model.dixing;
        const meshes = Helper.getChildMeshes(all);
        meshes.forEach(m => {
            (m.material as PBRMaterial).disableLighting = true;
        });
        const ground = Helper.nodeInArray(RawAssetsName.groundMesh, meshes, undefined, true) as Mesh;
        const _trees: AbstractMesh[] = [];
        Helper.nodeInArray(RawAssetsName.treeMesh, meshes, _trees, false) as Mesh;
        const tree = _trees[0] as Mesh;
        const grounds: Array<InstancedMesh> = [];
        const trees: Array<InstancedMesh> = [];
        for (let i = 0; i < 8; i++) {
            grounds.push(ground.createInstance(RawAssetsName.groundMesh + i));
            trees.push(tree.createInstance(RawAssetsName.treeMesh + i));
        }
        const extent = 1000;

        grounds[0].position.set(extent, 0, 0);
        trees[0].position.set(extent, 0, 0);

        grounds[1].position.set(-extent, 0, 0);
        trees[1].position.set(-extent, 0, 0);

        grounds[2].position.set(-extent, 0, extent);
        trees[2].position.set(-extent, 0, extent);

        grounds[3].position.set(extent, 0, -extent);
        trees[3].position.set(extent, 0, -extent);

        grounds[4].position.set(extent, 0, extent);
        trees[4].position.set(extent, 0, extent);

        grounds[5].position.set(-extent, 0, -extent);
        trees[5].position.set(-extent, 0, -extent);

        grounds[6].position.set(0, 0, extent);
        trees[6].position.set(0, 0, extent);

        grounds[7].position.set(0, 0, -extent);
        trees[7].position.set(0, 0, -extent);
    }

}


export { Landscape };